home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / viewers / mpgplyr1.lha / src / fs4.c < prev    next >
C/C++ Source or Header  |  1992-12-08  |  8KB  |  305 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  * 
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  * 
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. /* This file contains C code to do YCrCb -> colormap space. */
  22.  
  23. #include "fs4.h"
  24. #include "video.h"
  25. #include "dither.h"
  26.  
  27. /* Structures containing precomputed error terms. */
  28.  
  29. static FS4Dither lum_index[256];
  30. static FS4Dither cr_index[256];
  31. static FS4Dither cb_index[256];
  32.  
  33.  
  34. /*
  35.  *--------------------------------------------------------------
  36.  *
  37.  * InitFS4Dither --
  38.  *
  39.  *    Initializes structures used for f-s dithering. Precomputes
  40.  *      error terms.
  41.  *
  42.  * Results:
  43.  *    None.
  44.  *
  45.  * Side effects:
  46.  *      None.
  47.  *
  48.  *--------------------------------------------------------------
  49.  */
  50.  
  51. void
  52. InitFS4Dither()
  53. {
  54.   int i;
  55.  
  56.   for (i=0; i<256; i++) {
  57.     lum_index[i].value = (i * LUM_RANGE) / 256;
  58.  
  59.     lum_index[i].e1 = (7 * (i-lum_values[lum_index[i].value])) / 16;
  60.     lum_index[i].e2 = (i-lum_values[lum_index[i].value])/16;
  61.     lum_index[i].e3 = (5 *  (i - lum_values[lum_index[i].value])) / 16;
  62.     lum_index[i].e4 = (i-lum_values[lum_index[i].value]) - lum_index[i].e1 -
  63.       lum_index[i].e2 - lum_index[i].e3;
  64.  
  65.     lum_index[i].value *= LUM_BASE;
  66.  
  67.     cr_index[i].value = (i * CR_RANGE) / 256; 
  68.  
  69.     cr_index[i].e1 = (7 * (i-cr_values[cr_index[i].value])) / 16;
  70.     cr_index[i].e2 = (i-cr_values[cr_index[i].value])/16;
  71.     cr_index[i].e3 = (5 *  (i - cr_values[cr_index[i].value])) / 16;
  72.     cr_index[i].e4 = (i-cr_values[cr_index[i].value]) - cr_index[i].e1 -
  73.       cr_index[i].e2 - cr_index[i].e3;
  74.     cr_index[i].value *= CR_BASE;
  75.  
  76.     cb_index[i].value = (i * CB_RANGE) / 256; 
  77.  
  78.     cb_index[i].e1 = (7 * (i-cb_values[cb_index[i].value])) / 16;
  79.     cb_index[i].e2 = (i-cb_values[cb_index[i].value])/16;
  80.     cb_index[i].e3 = (5 *  (i - cb_values[cb_index[i].value])) / 16;
  81.     cb_index[i].e4 = (i-cb_values[cb_index[i].value]) - cb_index[i].e1 -
  82.       cb_index[i].e2 - cb_index[i].e3;
  83.     cb_index[i].value *= CB_BASE;
  84.  
  85.   }
  86.  
  87. }
  88.  
  89.  
  90. /*
  91.  *--------------------------------------------------------------
  92.  *
  93.  * DitherImage --
  94.  *
  95.  *    Converts lum, cr, cb image planes into fixed colormap
  96.  *      space. Uses Floyd-Steinberg dithering in serpentine
  97.  *      pattern with standard 4 errors propogated.
  98.  *
  99.  * Results:
  100.  *    The display plane is replaced by 8-bit colormap space
  101.  *      image.
  102.  *
  103.  * Side effects:
  104.  *      Hopefully, none.
  105.  *
  106.  *--------------------------------------------------------------
  107.  */
  108.  
  109. void 
  110. FS4DitherImage(lum, cr, cb, disp, rows, cols)
  111.      unsigned char *lum, *cr, *cb, *disp;
  112.      int rows, cols;
  113. {
  114.   static char *cur_row_error, *next_row_error;
  115.   static int first = 1;
  116.   char  *cur_row_err_mark, *next_row_err_mark;
  117.   char *temp;
  118.   int i, j, pixsum, c_cols;
  119.   unsigned char *cur_row, *channel, *dest_row;
  120.   FS4Dither *chan_index;
  121.  
  122.   if (first) {
  123.     cur_row_error = (char *) malloc(cols+2);
  124.     next_row_error = (char *) malloc(cols+2);
  125.     first = 0;
  126.   }
  127.  
  128.   memset(cur_row_error, 0, cols+2);
  129.   memset(next_row_error, 0, cols+2);
  130.  
  131.   for(i=0; i<rows; i+=2) {
  132.      cur_row = lum + (i*cols);
  133.      dest_row = disp + (i*cols);
  134.  
  135.      cur_row_err_mark = cur_row_error + 1;
  136.      next_row_err_mark = next_row_error + 1;
  137.  
  138.      for (j=0; j<cols; j++) {
  139.  
  140.        pixsum = *cur_row + *cur_row_err_mark;
  141.        if (pixsum < 0) pixsum = 0;
  142.        else if (pixsum > 255) pixsum = 255;
  143.  
  144.        *dest_row = lum_index[pixsum].value;
  145.        *(cur_row_err_mark+1) += lum_index[pixsum].e1; 
  146.        *(next_row_err_mark+1) += lum_index[pixsum].e2;
  147.        *next_row_err_mark += lum_index[pixsum].e3; 
  148.        *(next_row_err_mark-1) += lum_index[pixsum].e4;
  149.  
  150.        cur_row++;
  151.        dest_row++;
  152.        cur_row_err_mark++;
  153.        next_row_err_mark++;
  154.      }
  155.  
  156.      temp = cur_row_error;
  157.      cur_row_error = next_row_error;
  158.      next_row_error = temp;
  159.  
  160.      memset(next_row_error, 0, cols+2); 
  161.  
  162.      cur_row += cols-1;
  163.      dest_row += cols-1;
  164.      cur_row_err_mark = cur_row_error + cols;
  165.      next_row_err_mark = next_row_error + cols;
  166.  
  167.      for (j=0; j<cols; j++) {
  168.  
  169.        pixsum = *cur_row + *cur_row_err_mark;
  170.        if (pixsum < 0) pixsum = 0;
  171.        else if (pixsum > 255) pixsum = 255;
  172.  
  173.        *dest_row = lum_index[pixsum].value;
  174.        *(cur_row_err_mark-1) += lum_index[pixsum].e1; 
  175.        *(next_row_err_mark-1) += lum_index[pixsum].e2;
  176.        *next_row_err_mark += lum_index[pixsum].e3; 
  177.        *(next_row_err_mark+1) += lum_index[pixsum].e4;
  178.  
  179.        cur_row--;
  180.        dest_row--;
  181.        cur_row_err_mark--;
  182.        next_row_err_mark--;
  183.      }
  184.  
  185.      temp = cur_row_error;
  186.      cur_row_error = next_row_error;
  187.      next_row_error = temp;
  188.  
  189.      memset(next_row_error, 0, cols+2); 
  190.    }
  191.  
  192.   memset(cur_row_error, 0, cols+2); 
  193.  
  194.   c_cols = cols >> 1;
  195.  
  196.   channel = cr;
  197.   chan_index = cr_index;
  198.  
  199.  repeat:
  200.  
  201.   for (i=0; i < rows; i+=2) {
  202.     cur_row = channel + ((i>>1)*c_cols);
  203.     dest_row = disp + (i*cols);
  204.  
  205.     cur_row_err_mark = cur_row_error+1;
  206.     next_row_err_mark = next_row_error+1;
  207.     
  208.     for (j=0; j<cols; j++) {
  209.       int p_val;
  210.  
  211.       p_val = *cur_row;
  212.  
  213.       pixsum = *cur_row_err_mark + p_val;
  214.  
  215.       if (pixsum < 0) pixsum = 0;
  216.       else if (pixsum > 255) pixsum = 255;
  217.  
  218.       *dest_row += chan_index[pixsum].value;
  219.  
  220.       *(cur_row_err_mark+1) += chan_index[pixsum].e1; 
  221.       *(next_row_err_mark+1) += chan_index[pixsum].e2;
  222.       *next_row_err_mark += chan_index[pixsum].e3; 
  223.       *(next_row_err_mark-1) += chan_index[pixsum].e4;
  224.  
  225.  
  226.       if (j&1) cur_row++;
  227.       dest_row++;
  228.       cur_row_err_mark++;
  229.       next_row_err_mark++;
  230.     }
  231.       
  232.     temp = cur_row_error;
  233.     cur_row_error = next_row_error;
  234.     next_row_error = temp;
  235.  
  236.     memset(next_row_error, 0, cols+2);
  237.  
  238.     cur_row += c_cols-1;
  239.     dest_row += cols-1;
  240.     cur_row_err_mark = cur_row_error+cols;
  241.     next_row_err_mark = next_row_error+cols;
  242.  
  243.     for (j=0; j<cols; j++) {
  244.       int p_val;
  245.  
  246.       p_val = *cur_row;
  247.  
  248.       pixsum = *cur_row_err_mark + p_val;
  249.  
  250.       if (pixsum < 0) pixsum = 0;
  251.       else if (pixsum > 255) pixsum = 255;
  252.  
  253.       *dest_row += chan_index[pixsum].value;
  254.  
  255.       *(cur_row_err_mark-1) += chan_index[pixsum].e1; 
  256.       *(next_row_err_mark-1) += chan_index[pixsum].e2;
  257.       *next_row_err_mark += chan_index[pixsum].e3; 
  258.       *(next_row_err_mark+1) += chan_index[pixsum].e4;
  259.  
  260.       if (j&1) cur_row--;
  261.       dest_row--;
  262.       cur_row_err_mark--;
  263.       next_row_err_mark--;
  264.     }
  265.  
  266.     temp = cur_row_error;
  267.     cur_row_error = next_row_error;
  268.     next_row_error = temp;
  269.  
  270.     memset(next_row_error, 0, cols+2);
  271.   }
  272.  
  273.   if (channel == cr) {
  274.     channel = cb;
  275.     chan_index = cb_index;
  276.     memset(cur_row_error, 0, cols+2);
  277.  
  278.     goto repeat;
  279.   }
  280.  
  281.   dest_row = disp;
  282.  
  283.  
  284.   for (i=0; i<rows; i++) {
  285.     for (j=0; j<cols; j++) {
  286.       *dest_row =  pixel[*dest_row];
  287.       dest_row++;
  288.     }
  289.   }
  290. }
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.